
%language "Java"
%name-prefix ""

%code imports {
  import de.mmis.core.abstracttree.Tree;
  // suppress all warnings
  @SuppressWarnings("all")
}

%define package "de.mmis.core.publishsubscribe.filter"

%token <Tree> sexpression
%token <String> reference id
%token <Object> lpar rpar

%token <FilterOperator> fop
%token <BooleanOperator> bop_and bop_or bop_xor bop_implies bop_iff
%token <Object> not

%type <Filter> filter filter_start
%type <AtomicFilter> atomic exists compare2
%type <CompoundFilter> compound negate comparefilter

%type <FilterValue> value

%left bop_iff
%left bop_implies
%left bop_or
%left bop_xor
%left bop_and
%left not
%nonassoc fop

%code {
  Filter result;
}

%%

filter_start: filter { $$ = $1; result = $1; }
  ;

filter:
    atomic { $$ = $1; }
  | compound { $$ = $1; }
  ;

atomic:
    exists
  | compare2
  ;

exists:
    reference { $$ = new AtomicFilter($1); }
  ;

compare2:
    value fop value { $$ = new AtomicFilter($2, $1, $3); }
  ;

compound:
    negate
  | comparefilter
  | lpar filter rpar { $$ = $2; }
  ;

negate: not filter { $$ = new CompoundFilter($2); }
  ;

comparefilter:
    filter bop_and filter { $$ = new CompoundFilter($2, $1, $3); }
  | filter bop_or filter { $$ = new CompoundFilter($2, $1, $3); }
  | filter bop_xor filter { $$ = new CompoundFilter($2, $1, $3); }
  | filter bop_implies filter { $$ = new CompoundFilter($2, $1, $3); }
  | filter bop_iff filter { $$ = new CompoundFilter($2, $1, $3); }
  ;

value:
    reference { $$ = new FilterValue($1); }
  | sexpression { $$ = new FilterValue($1); }
  | reference id { $$ = new FilterValue($2, $1); }
  ;

%%

